package cn.hf.mychat.common.util;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 反射工具类
 * @author 白高建
 * @create 2020/1/20 14:22
 */
public class ReflectUtils {

    /**
     * 类中是否有指定字段，如果有 返回该字段的修饰符
     */
    public static <T> int getFieldModifier(Class<T> clazz, String field) throws Exception {
        Field[] fields = clazz.getDeclaredFields();

        for(int i = 0; i < fields.length; ++i) {
            if (fields[i].getName().equals(field)) {
                return fields[i].getModifiers();
            }
        }

        throw new Exception(clazz + " has no field \"" + field + "\"");
    }

    public static <T> int getMethodModifier(Class<T> clazz, String method) throws Exception {
        Method[] m = clazz.getDeclaredMethods();

        for(int i = 0; i < m.length; ++i) {
            if (m[i].getName().equals(m)) {
                return m[i].getModifiers();
            }
        }

        throw new Exception(clazz + " has no method \"" + m + "\"");
    }

    /**
     * 反射获取对象某个字段的值
     * @param clazzInstance 反射对象
     * @param field 字段名
     */
    public static <T> Object getFieldValue(Object clazzInstance, Object field) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
        Field[] fields = clazzInstance.getClass().getDeclaredFields();

        for(int i = 0; i < fields.length; ++i) {
            if (fields[i].getName().equals(field)) {
                fields[i].setAccessible(true);//Accessable属性是继承自AccessibleObject 类. 功能是启用或禁用安全检查
                return fields[i].get(clazzInstance);
            }
        }

        return null;
    }

    public static <T> Object getFieldValue(Class<T> clazz, String field) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, InstantiationException {
        Field[] fields = clazz.getDeclaredFields();

        for(int i = 0; i < fields.length; ++i) {
            if (fields[i].getName().equals(field)) {
                fields[i].setAccessible(true);
                return fields[i].get(clazz.newInstance());
            }
        }

        return null;
    }

    public static <T> String[] getFields(Class<T> clazz) {
        Field[] fields = clazz.getDeclaredFields();
        String[] fieldsArray = new String[fields.length];

        for(int i = 0; i < fields.length; ++i) {
            fieldsArray[i] = fields[i].getName();
        }

        return fieldsArray;
    }

    public static <T> Field[] getClassFieldsAndSuperClassFields(Class<T> clazz) throws Exception {
        Field[] fields = clazz.getDeclaredFields();
        if (clazz.getSuperclass() == null) {
            throw new Exception(clazz.getName() + "没有父类");
        } else {
            Field[] superFields = clazz.getSuperclass().getDeclaredFields();
            Field[] allFields = new Field[fields.length + superFields.length];

            int i;
            for(i = 0; i < fields.length; ++i) {
                allFields[i] = fields[i];
            }

            for(i = 0; i < superFields.length; ++i) {
                allFields[fields.length + i] = superFields[i];
            }

            return allFields;
        }
    }

    public static <T> Object invoke(Class<T> clazz, String method) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
        Object instance = clazz.newInstance();
        Method m = clazz.getMethod(method);
        return m.invoke(instance);
    }

    public static <T> Object invoke(Object clazzInstance, String method) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
        Method m = clazzInstance.getClass().getMethod(method);
        return m.invoke(clazzInstance);
    }

    public static <T> Object invoke(Class<T> clazz, String method, Class<T>[] paramClasses, Object[] params) throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
        Object instance = clazz.newInstance();
        Method _m = clazz.getMethod(method, paramClasses);
        return _m.invoke(instance, params);
    }

    public static <T> Object invoke(Object clazzInstance, String method, Class<T>[] paramClasses, Object[] params) throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
        Method _m = clazzInstance.getClass().getMethod(method, paramClasses);
        return _m.invoke(clazzInstance, params);
    }

}
